// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Based on codec_wrapper.h originally written by
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. 

#ifndef MEDIA_GPU_OHOS_CODEC_WRAPPER_H_
#define MEDIA_GPU_OHOS_CODEC_WRAPPER_H_

#include <stddef.h>
#include <stdint.h>

#include <memory>
#include <vector>

#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "media/base/decoder_buffer.h"
#include "media/base/ohos/ohos_media_decoder_bridge_impl.h"
#include "media/gpu/media_gpu_export.h"
#include "media/gpu/ohos/codec_surface_bundle.h"

namespace media {
class CodecWrapper;
class CodecWrapperImpl;

using namespace OHOS::NWeb;

using CodecSurfacePair = std::pair<std::unique_ptr<MediaCodecDecoderBridgeImpl>,
                                   scoped_refptr<CodecSurfaceBundle>>;

class MEDIA_GPU_EXPORT CodecOutputBuffer {
 public:
  CodecOutputBuffer(const CodecOutputBuffer&) = delete;
  CodecOutputBuffer& operator=(const CodecOutputBuffer&) = delete;

  ~CodecOutputBuffer();

  bool ReleaseToSurface();

  gfx::Size size() const { return size_; }

  void set_render_cb(base::OnceClosure render_cb) {
    render_cb_ = std::move(render_cb);
  }

  const gfx::ColorSpace& color_space() const { return color_space_; }

#if BUILDFLAG(ARKWEB_VIDEO_ASSISTANT)
  bool RenderVideoView() { return render_video_view_; }
#endif // ARKWEB_VIDEO_ASSISTANT

 private:
  friend class CodecWrapperImpl;
  CodecOutputBuffer(scoped_refptr<CodecWrapperImpl> codec,
                    int64_t id,
                    const gfx::Size& size,
#if BUILDFLAG(ARKWEB_VIDEO_ASSISTANT)
                    bool render_video_view,
#endif // ARKWEB_VIDEO_ASSISTANT
                    const gfx::ColorSpace& color_space);

  scoped_refptr<CodecWrapperImpl> codec_;
  int64_t id_;
  bool was_rendered_ = false;
  gfx::Size size_;
  base::OnceClosure render_cb_;
#if BUILDFLAG(ARKWEB_VIDEO_ASSISTANT)
  bool render_video_view_ = false;
#endif // ARKWEB_VIDEO_ASSISTANT
  gfx::ColorSpace color_space_;
};

class MEDIA_GPU_EXPORT CodecWrapper {
 public:
  using OutputReleasedCB = base::RepeatingCallback<void(bool)>;
  CodecWrapper(CodecSurfacePair codec_surface_pair,
               OutputReleasedCB output_buffer_release_cb,
               scoped_refptr<base::SequencedTaskRunner> release_task_runner);

  CodecWrapper(const CodecWrapper&) = delete;
  CodecWrapper& operator=(const CodecWrapper&) = delete;

  ~CodecWrapper();

  CodecSurfacePair TakeCodecSurfacePair();

  bool IsFlushed() const;

  bool IsDraining() const;

  bool IsDrained() const;

  bool HasUnreleasedOutputBuffers() const;

  void DiscardOutputBuffers();

  bool Flush();

  bool SetSurface(scoped_refptr<CodecSurfaceBundle> surface_bundle);

#if BUILDFLAG(ARKWEB_VIDEO_ASSISTANT)
  void SetVideoSurface(int32_t widget_id);
#endif // ARKWEB_VIDEO_ASSISTANT

#if BUILDFLAG(ARKWEB_MEDIA_DMABUF)
  void RecycleDmaBuffer();
  void ResumeDmaBuffer();
#endif  // ARKWEB_MEDIA_DMABUF

  scoped_refptr<CodecSurfaceBundle> SurfaceBundle();

  enum class QueueStatus { kOk, kError, kTryAgainLater, kNoKey };
  QueueStatus QueueInputBuffer(const DecoderBuffer& buffer);

  enum class DequeueStatus { kOk, kError, kTryAgainLater };
  DequeueStatus DequeueOutputBuffer(
      base::TimeDelta* presentation_time,
      bool* end_of_stream,
      std::unique_ptr<CodecOutputBuffer>* codec_buffer);

  bool SetDecryptionConfig(void *session, bool isSecure);

 private:
  scoped_refptr<CodecWrapperImpl> impl_;
};

}  // namespace media

#endif  // MEDIA_GPU_OHOS_CODEC_WRAPPER_H_
